/*
 * JSF Toolkit Component Framework
 * Copyright (C) 2007 Noah Sloan <iamnoah A-T gmail D0T com>
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 */
package com.jsftoolkit.base;

import com.jsftoolkit.utils.Utils;

/**
 * Describes an include in an HTML page, e.g. a script or stylesheet.
 * 
 * <dl>
 * <dt>id</dt>
 * <dd>A unique identifier for the resource. It is recommended that it be of
 * the form "com.yourcompany.package.ComponentClass.RESOURCENAME_EXT"</dd>
 * <dt>defaultResource</dt>
 * <dd>The classpath resource to load if one is not specified by other means.</dd>
 * <dt>encoding (optional)</dt>
 * <dd>The encoding to use when reading in the resource (may be overridden).</dd>
 * <dt>filter (optional)</dt>
 * <dd>The <em>name</em> of the managed bean that will convert embedded
 * resource paths into appropriate remoting URLs. Note that this is the actual
 * name, not a value binding.</dd>
 * </dl>
 * Each of the defaults, resource, encoding and bean, may be overridden in the
 * following order:
 * 
 * <ol>
 * <li> If there is a web.xml initialization parameter with the name of the
 * attribute, it will be used.
 * <li>Otherwise, the default value is used.
 * </ol>
 * The attribute name is: the Resource ID for the resource, the Resource ID +
 * '.ENCODING' for the encoding, and the Resource ID + '.BEAN' for the bean.
 * e.g. specifying
 * com.yourcompany.package.ComponentClass.RESOURCENAME_EXT="/com/clientcompany/theResource.ext"
 * in web.xml will override the resource for all instances of that component.
 * 
 * 
 * @author noah
 * 
 */
public class ResourceInfo {

	/**
	 * Defines the content types. SCRIPT for javascript and STYLE for css.
	 * 
	 * @author noah
	 * 
	 */
	public enum Type {
		SCRIPT("text/javascript"), STYLE("text/css");

		private String contentType;

		private Type(String type) {
			this.contentType = type;
		}

		@Override
		public String toString() {
			return contentType;
		}

		public static Type decode(String name) {
			for (Type type : values()) {
				if (type.name().equalsIgnoreCase(name)) {
					return type;
				}
			}
			return null;
		}
	};

	private String id;

	private String defaultResource;

	private String encoding;

	private String filter;

	private Type type;

	public ResourceInfo() {
		super();
	}

	/**
	 * Any of the parameters except id and defaultResource may be null.
	 * 
	 * @param id
	 *            the id of the resource, used for loading defaults from web.xml
	 *            and as the attribute name on the component for instance
	 *            override. A good id would be the canonical class name of the
	 *            component + the filename of the resource converted to
	 *            uppercase. e.g. com.jsftoolkit.components.dnd.DragItem.DOJO_JS
	 * @param defaultResource
	 *            the classpath resource to load be default
	 * @param type
	 *            the type of the resource
	 * @param encoding
	 * @param filter
	 */
	public ResourceInfo(final String id, final String defaultResource,
			final Type type, String encoding, String filter) {
		this();
		this.id = id;
		this.defaultResource = defaultResource;
		this.type = type;
		this.encoding = encoding;
		this.filter = filter;
	}

	/**
	 * 
	 * @return the default classpath resource to use
	 */
	public String getDefaultResource() {
		return defaultResource;
	}

	/**
	 * 
	 * @return the ID of this resource
	 */
	public String getId() {
		return id;
	}

	/**
	 * 
	 * @return the type of this resource.
	 */
	public Type getResourceType() {
		return type;
	}

	/**
	 * For Digester, since it can't handle enums.
	 * 
	 * @return the toString of resource type
	 */
	public String getType() {
		return type == null ? null : type.name();
	}

	/**
	 * 
	 * @return the encoding of the resource.
	 */
	public String getEncoding() {
		return encoding;
	}

	/**
	 * 
	 * @return the name of the managed bean that should filter the resource.
	 */
	public String getFilter() {
		return filter;
	}

	public void setDefaultResource(String defaultResource) {
		this.defaultResource = defaultResource;
	}

	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}

	public void setFilter(String filter) {
		this.filter = filter;
	}

	public void setId(String id) {
		this.id = id;
	}

	/**
	 * For Commons Digester.
	 * 
	 * @param type
	 */
	public void setType(String type) {
		this.type = Type.decode(type);
	}

	public void setResourceType(Type type) {
		this.type = type;
	}

	/**
	 * Return a java code representation of this resource.
	 */
	public CharSequence getCodeString() {
		return String.format("new %s(\"%s\",\"%s\",%s,%s,%s)", getClass()
				.getSimpleName(), id, defaultResource, type == null ? "null"
				: Type.class.getSimpleName() + '.' + type.name(), Utils
				.toStringConstant(encoding), Utils.toStringConstant(filter));
	}

	/**
	 * Identity is based on id.
	 */
	@Override
	public int hashCode() {
		final int PRIME = 31;
		int result = 1;
		result = PRIME * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	/**
	 * Identity is based on id.
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		final ResourceInfo other = (ResourceInfo) obj;
		if (id == null) {
			if (other.id != null) {
				return false;
			}
		} else if (!id.equals(other.id)) {
			return false;
		}
		return true;
	}

}
